--[[
--
--  commandline
--
--]]

function crt_cmd(msg)
  local CMD = {strsplit(" ",msg)};
  
  local valid=false;
  if string.lower(tostring(CMD[1])) == "new" then crt_newElement(CMD[2]) -- create ne welement
  elseif string.lower(tostring(CMD[1])) == "delete" then crt_deleteByName(CMD[2]) -- delete element
  elseif string.lower(tostring(CMD[1])) == "profile" then -- profile submenu
   if string.lower(tostring(CMD[2])) == "select" then crt_selectProfile(CMD[3]) end 
   if string.lower(tostring(CMD[2])) == "new" then crt_newProfile(CMD[3]) end
  elseif string.lower(tostring(CMD[1])) == "set" then -- setting submenu
   for i,v in pairs(crt[crt_activeProfile]) do -- check if object is existing
    if v["elementName"] == CMD[2] then valid = true;
   end
   if valid then
    if v["elementName"] == CMD[2] then -- it exists
     if string.lower(tostring(CMD[3])) == "value" then 
	  local value = ""; for x=4,#(CMD) do value = value..tostring(CMD[x]).." "; end
	  crt_setAttribute(CMD[2],"elementTypeData.value",strsub(value,0,-2)); return true;-- change value
	  
	       elseif string.lower(tostring(CMD[3])) == "font" then -- submenu
	  if string.lower(tostring(CMD[4])) == "face" then 
	  local value = ""; for x=5,#(CMD) do value = value..tostring(CMD[x]).." "; end
	  DEFAULT_CHAT_FRAME:AddMessage(value);
	  crt_setAttribute(CMD[2],"elementTypeData.fontFace",strsub(value,0,-2)); return true; -- change AnchorTo
	  elseif string.lower(tostring(CMD[4])) == "size" then crt_setAttribute(CMD[2],"elementTypeData.fontSize",CMD[5]); return true; -- change RelativeTo
	  elseif string.lower(tostring(CMD[4])) == "style" then crt_setAttribute(CMD[2],"elementTypeData.fontStyle",string.upper(CMD[5])); return true; -- change RelativePoint

	  else -- describe level
	   DEFAULT_CHAT_FRAME:AddMessage("Attribut '|cffff8900"..tostring(CMD[3]).."|r' has the following subattributes : {face, size, style}"); return false;
	  end
	  
	       elseif string.lower(tostring(CMD[3])) == "shadow" then -- submenu
	  if string.lower(tostring(CMD[4])) == "color" then crt_setAttribute(CMD[2],"elementTypeData.shadowColor",CMD[5]); return true; -- change AnchorTo
	  elseif string.lower(tostring(CMD[4])) == "offset" then -- submenu
	  if string.lower(tostring(CMD[5])) == "x" then crt_setAttribute(CMD[2],"elementTypeData.shadowOffset.X",tonumber(CMD[6])); return true; -- change AnchorTo
	  elseif string.lower(tostring(CMD[5])) == "y" then crt_setAttribute(CMD[2],"elementTypeData.shadowOffset.Y",tonumber(CMD[6])); return true; -- change RelativeTo

	  else -- describe level
	   DEFAULT_CHAT_FRAME:AddMessage("Attribut '|cffff8900"..tostring(CMD[3]).."|r' has the following subattributes : {X,Y}"); return false;
	  end
	
	  else -- describe level
	   DEFAULT_CHAT_FRAME:AddMessage("Attribut '|cffff8900"..tostring(CMD[3]).."|r' has the following subattributes : {color, offset}"); return false;
	  end
		
  
     elseif string.lower(tostring(CMD[3])) == "isdogtag" then crt_setAttribute(CMD[2],"elementTypeData.IsDogTagged",CMD[4]); return true; -- change dogtagstatus	 
     elseif string.lower(tostring(CMD[3])) == "justification" then -- submenu
	  if string.lower(tostring(CMD[4])) == "anchorpoint" then crt_setAttribute(CMD[2],"elementJustification.point.AnchorTo",string.upper(CMD[5])); return true; -- change AnchorTo
	  elseif string.lower(tostring(CMD[4])) == "anchorframe" then crt_setAttribute(CMD[2],"elementJustification.point.RelativeTo",CMD[5]); return true; -- change RelativeTo
	  elseif string.lower(tostring(CMD[4])) == "relativeto" then crt_setAttribute(CMD[2],"elementJustification.point.RelativePoint",string.upper(CMD[5])); return true; -- change RelativePoint
	  elseif string.lower(tostring(CMD[4])) == "offsetx" then crt_setAttribute(CMD[2],"elementJustification.point.OffsetX",tonumber(CMD[5])); return true; -- change Offset X
	  elseif string.lower(tostring(CMD[4])) == "offsety" then crt_setAttribute(CMD[2],"elementJustification.point.OffsetY",tonumber(CMD[5])); return true; -- change Offset Y
	  elseif string.lower(tostring(CMD[4])) == "level" then crt_setAttribute(CMD[2],"elementJustification.frameLevel",tonumber(CMD[5])); return true; -- change FrameLevel
	  elseif string.lower(tostring(CMD[4])) == "strata" then crt_setAttribute(CMD[2],"elementJustification.frameStrata",string.upper(CMD[5])); return true; -- change FrameStrata
	  else -- describe level
	   DEFAULT_CHAT_FRAME:AddMessage("Attribut '|cffff8900"..tostring(CMD[3]).."|r' has the following subattributes : {anchorpoint, anchorframe, relativeto, offsetx, offsety, level, strata}"); return false;
	  end
	  
	 elseif string.lower(tostring(CMD[3])) == "relative" then crt_setAttribute(CMD[2],"elementRelative",CMD[4]); return true; -- change Unit Relative
	 elseif string.lower(tostring(CMD[3])) == "clickable" then crt_setAttribute(CMD[2],"elementClickable",CMD[4]); return true; -- change Unit Relative
	 elseif string.lower(tostring(CMD[3])) == "name" then crt_setAttribute(CMD[2],"elementName",CMD[4]); return true; -- change Label Name
	 elseif string.lower(tostring(CMD[3])) == "scripts" then crt_setAttribute(CMD[2],"elementScripts."..CMD[4],CMD[5]); return true; -- change Scripts
	 else
	  DEFAULT_CHAT_FRAME:AddMessage("Element '|cffff8900"..tostring(CMD[2]).."|r' has the following attributes : {value, font, shadow, isdogtag, justification, relative, clickable, name, scripts}"); return false;	
	 end
     end
	 end
	end 
  elseif string.lower(tostring(CMD[1])) == "gui" then 
  local loaded, reason = LoadAddOn("crt_registry")
  if not loaded then
  if reason == "DISABLED" then
    DEFAULT_CHAT_FRAME:AddMessage("Cannot initialize |cffff8900Registry Module|r reason: module is disabled")
  elseif reason == "MISSING" then
    DEFAULT_CHAT_FRAME:AddMessage("Cannot initialize |cffff8900Registry Module|r reason: module is missing")
  elseif reason == "CORRUPT" then
    DEFAULT_CHAT_FRAME:AddMessage("Cannot initialize |cffff8900Registry Module|r reason: module is corrupt")
  elseif reason == "INTERFACE_VERSION" then
    DEFAULT_CHAT_FRAME:AddMessage("Cannot initialize |cffff8900Registry Module|r reason: module is too old")
  end
  else
   crc_toggle(); 
  end 
  else
 DEFAULT_CHAT_FRAME:AddMessage("CRT '"..crt_version.."' has the following attributes : {new, delete, profile, set, gui}"); return false;
 end
end	

	  SLASH_CRT1 = "/crt";
	  SlashCmdList["CRT"] = crt_cmd;

function crt_deleteProfile(profileName) -- delete a profile
 local dataSource = crt;
 local success = false;
 for k,v in pairs(crt) do
  if v["ProfileName"] == profileName then tremove(dataSource,k); success = true end
 end
end	  
	  
function crt_newProfile(profileName) -- create a new profile
 local dataSource = crt;
 local success = true;
 for k,v in pairs(crt) do
  if v["ProfileName"] == profileName then success = false end -- profile is already existing
 end
 if success then
  tinsert(crt, crt_default[1]);
  crt[#(crt)]["ProfileName"] = profileName;
     DEFAULT_CHAT_FRAME:AddMessage("Profile '|cffff8900"..profileName.."|r' successfully created.");
 else
     DEFAULT_CHAT_FRAME:AddMessage("Profile '|cffff8900"..profileName.."|r' is already existing.");
 end
end
function crt_selectProfile(profileName) -- select a other profile 
local oldProfile = crt_activeProfile;
local success = false;
for i,v in pairs(crt[crt_activeProfile]) do
 if v["elementName"] ~= nil then
 local panel = getglobal("CRT_"..v["elementName"]);
 if panel:GetObjectType() == "Button" then
 panel:Hide();
 panel = nil;
 end
 end
end
for k,v in pairs(crt) do
  if v["ProfileName"] == profileName then
   crt_activeProfile = k;
   success = true;
  end
 end
 if success then
     for i,v in pairs(crt[crt_activeProfile]) do
	  if v["elementName"] ~= nil then
	  crt_RequestUpdate(i,crt[crt_activeProfile])
	  end
	 end
     DEFAULT_CHAT_FRAME:AddMessage("Profile '|cffff8900"..profileName.."|r' is now selected. Its better to reload the UI for fully effect."); 

 else
     DEFAULT_CHAT_FRAME:AddMessage("Profile '|cffff8900"..profileName.."|r' does not exists, create it first."); 
 end
end
-- element specific Commands
function crt_unlockElement(elementName) -- make the Element dragable
 local dataSource = crt[crt_activeProfile];
 for i,v in pairs(dataSource) do
  if v["elementName"] == elementName then
   local f = getglobal("CRT_"..elementName);
   f.moving = true;
   f:EnableMouse(true);
   f:RegisterForDrag("RightButton");
   f:ClearAllPoints();
   f:SetMovable(true);
   f:RegisterEvent("OnDragStart",function() startMoving(); end);
   f:RegisterEvent("OnDragStop",
   function() 
    StopMovingOrSizing(); 
    local newAnchorTo, newRelativeTo, newRelativePoint, newOffsetX, newOffsetY = this:GetPoint(1);
    crt_setAttribute(elementName,"elementJustification.point.OffsetX",newOffsetX);
	crt_setAttribute(elementName,"elementJustification.point.OffsetY",newOffsetY);
   end);
   
  end
 end
end
function crt_lockElement(elementName) -- make the Element non-dragable
 local dataSource = crt[crt_activeProfile];
 for i,v in pairs(dataSource) do
  if v["elementName"] == elementName then
   f = getglobal("CRT_"..elementName);
   f.moving = false;
   if f.clickable == false then
    f:EnableMouse(false);
   end
   f:SetMovable(false);
   f:RegisterForDrag("");
   f:UnregisterEvent("OnDragStart");
   f:UnregisterEvent("OnDragStop");
  end
 end
end
function crt_getAttribute(elementName, attribute, silent) -- get Attribut from element
 local dataSource = crt[crt_activeProfile];
 local elementProperty;
 for i,v in pairs(dataSource) do
  if v["elementName"] == elementName then
   local key1, key2,key3, key4 = strsplit(".",attribute);
   if key1 ~= nil then
    if key2 ~= nil then
	 if key3 ~= nil then
	  if key4 ~= nil then
	   elementProperty = v[key1][key2][key3][key4];
	   success = true;
 	  else
	   elementProperty = v[key1][key2][key3];
	   success = true;
	  end
	 else
       elementProperty = v[key1][key2];
	   success = true;
	 end
	else
    elementProperty = v[key1];
	success = true;
   end
   end
  end
 end  
 if success then
  if silent ~= true or elementProperty ~= nil or type(elementProperty) ~= "boolean" then
 -- DEFAULT_CHAT_FRAME:AddMessage("Attribut '|cffff8900"..attribute.."|r' of Element '|cffff8900"..elementName.."|r' is set to '|cffff8900"..elementProperty.."|r'");
  end
 return elementProperty;
 else
 return 0;
 end
end
function crt_setAttribute(elementName, attribute, newvalue, silent) -- set Attribut
local dataSource = crt[crt_activeProfile];
local success = false;

 for i,v in pairs(dataSource) do
  if v["elementName"] == elementName then
   local key1,key2,key3,key4 = strsplit(".",attribute);
   
   if key1 ~= nil then
    if key2 ~= nil then
	 if key3 ~= nil then
	  if key4 ~= nil then
	   v[key1][key2][key3][key4] = newvalue;
	   success = true;
       crt_RequestUpdate(i, dataSource);
	  else
	   v[key1][key2][key3] = newvalue;
	   success = true;
       crt_RequestUpdate(i, dataSource);
	  end
	 else
	  v[key1][key2] = newvalue;
	  success = true;
      crt_RequestUpdate(i, dataSource);
	 end
	else
	v[key1] = newvalue;
	success = true;
    crt_RequestUpdate(i, dataSource);
   end
   end
  end
  
 end
 if success then
  if silent ~= true then
 DEFAULT_CHAT_FRAME:AddMessage("Attribut '|cffff8900"..attribute.."|r' of Element '|cffff8900"..elementName.."|r' is now set to '|cffff8900"..newvalue.."|r'");
  end
  return success;
 end
end
function crt_newElement(elementName) -- create a new Element
local dataSource = crt[crt_activeProfile];
local success =true;
local newElement = {
["elementName"] = elementName,
	 ["elementRelative"] = "player",
	 ["elementJustification"] = {
	  ["frameStrata"] = "LOW",
	  ["frameLevel"] = "1",
				["point"] = {
					["AnchorTo"] = "CENTER", -- [1]
					["RelativeTo"] = "UIParent", -- [2]
					["RelativePoint"] = "CENTER", -- [3]
					["OffsetX"] = 0, -- [4]
					["OffsetY"] = 0, -- [5]
				},},
	 ["elementTypeData"] = {
	  ["fontFace"] = "fonts/FRIZQT__.ttf", ["fontSize"] = 12, ["fontStyle"] = "NONE",
	  ["value"] = "new Element",
	  ["IsDogTagged"] = false,
	  ["shadowColor"] = {0,0,0,1},
	  ["shadowOffset"] = {
	   ["X"] = -1,
       ["Y"] =  0
	  },
	 },
   };
   for i,v in pairs(dataSource) do
    if v["elementName"] == elementName then sucess = false
	end
   end
  if success then 
   DEFAULT_CHAT_FRAME:AddMessage("Element '|cffff8900"..elementName.."|r' successfully created.");
   tinsert(dataSource, newElement);
   crt_RequestUpdate(#(dataSource), dataSource);
  else
   DEFAULT_CHAT_FRAME:AddMessage("Element '|cffff8900"..elementName.."|r' is already existing please use a other name.");
  end
end
function crt_deleteByName(elementName) -- delete Element
local dataSource = crt[crt_activeProfile];
local success = false;
 for i,v in pairs(dataSource) do
  if v["elementName"] == elementName then
   getglobal("CRT_"..v["elementName"]):Hide();
   tremove(dataSource, i);
  end
 end
 if success then
  DEFAULT_CHAT_FRAME:AddMessage("Element '|cffff8900"..elementName.."|r' is now deleted.");
 end
end
function crt_cloneElement(elementName, newElementName) -- clone Element
local dataSource = crt[crt_activeProfile]; 
local success = false;
local source;
 for i,v in pairs(dataSource) do
  if v["elementName"] == elementName then
   source = v;
   local copy = v;
    copy["elementName"] = newElementName;
	tinsert(dataSource, copy);
	success = true;
  end
 end
 source["elementName"] = elementName;
 return success;
end
